package ru.nlezhnev.utils;

import java.util.Map;

import flex.messaging.io.amf.ASObject;

public class ASObjectUtils {
	@SuppressWarnings("unchecked")
	static public void replaceNativeArrays(Object data) {
		if (data instanceof ASObject) {
			ASObject asObj = (ASObject) data;
			for (Object key : asObj.keySet()) {
				if (asObj.get(key) instanceof Object[]) {
					ASObject converted = array2asObject((Object[])asObj.get(key));
					asObj.put(key, converted);
				}
				replaceNativeArrays(asObj.get(key));
			}			
		}
	}
	
	@SuppressWarnings("unchecked")
	static private ASObject array2asObject(Object[] array) {
		ASObject result = new ASObject();
		for (int i = 0; i < array.length; i++) {
			result.put(i, array[i]);
		}
		return result;
	}
	
	/** replace ASObject's on Object[], if it have dense keys */
	@SuppressWarnings("unchecked")
	static public void replaceAsObjectsToArrays(Object data) {
		if (data instanceof ASObject) {
			ASObject asObj = (ASObject) data;
			for (Object key : asObj.keySet()) {
				if (asObj.get(key) instanceof ASObject && isDenseArray((ASObject)asObj.get(key))) {					
					ASObject value = (ASObject)asObj.get(key);					
					asObj.put(key, asObjectToArray(value));
				}
				replaceAsObjectsToArrays(asObj.get(key));
			}			
		} else if (data instanceof Object[]){
			Object[] dataArray = (Object[]) data;
			
			for (int index = 0; index < dataArray.length; index++) {
				if (dataArray[index] instanceof ASObject && isDenseArray((ASObject)dataArray[index])) {					
					ASObject value = (ASObject)dataArray[index];
					dataArray[index] = asObjectToArray(value);
				}
				replaceAsObjectsToArrays(dataArray[index]);
			}
		}
	}
	
	static private Object[] asObjectToArray(ASObject asObj) {
		Object[] result = new Object[asObj.size()];
		for (Object key : asObj.keySet()) {
			result[(Integer)key] = asObj.get(key);
		}
		return result;
	}
	
	static private boolean isDenseArray(Map<?, ?> map) {
		int maxIndex = -1;
		for (Object key : map.keySet()) {
			if (!(key instanceof Integer)) {
				return false;
			} else {
				int index = (Integer)key;
				maxIndex = Math.max(maxIndex, index);
			}
		}
		return map.size() == maxIndex + 1;
	}
	
	@SuppressWarnings("unchecked")
	static public ASObject makeByPath(String[] path, Object value) {
		ASObject result = new ASObject();
		result.put(path[path.length - 1], value);
		for (int i = path.length - 2; i >= 0; i--) {
			ASObject tempValue = result;
			result = new ASObject();
			result.put(path[i], tempValue);
		}		
		return result;
	}
	
	//@SuppressWarnings("unchecked")
	static public ASObject getByPath(String[] path, ASObject from) {
		ASObject curr = from;
		for (String key : path) {
			curr = (ASObject)curr.get(key);
			if (curr == null && !(curr instanceof ASObject)) {
				return null;
			}
		}
		return curr;
	}
	
	static public void deleteByPath(String[] path, ASObject data) {
		try {
			ASObject curr = data;
			for (int i = 0; i < path.length-1; i ++) {
				curr = (ASObject) curr.get(path[i]);
			}
			curr.remove(path[path.length - 1]);
		} catch (NullPointerException e) {
			return; //path not found
		}
	}
}
